package gitobject;
import repository.Repository;
//import zlib.ZLibUtils;
import zlib.ZLibUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;

import fileoperation.FileCreation;


public class GitObject implements Serializable {

    private static final long serialVersionUID = -4135082689793118188L;
    protected String fmt;                  //type of object
    protected String key;                  //key of object
    protected String mode;                 //mode of object
    protected static String path = Repository.getGitDir() + File.separator + "objects";          //absolute path of objects
    protected String value;                //value of object
    protected String name;                 //name of object

    public String getFmt(){
        return fmt;
    }
    public String getKey() { return key; }
    public String getMode(){
        return mode;
    }
    public String getPath() {
        return path;
    }
    public String getValue(){
        return value;
    }
    public String getName(){
        return name;
    }


    public GitObject(){}
    /**
     * Get the value(content) of file
     * @param file
     * @return String
     * @throws IOException
     */
    public static String getValue(File file) throws IOException {
        String content = null;
        try {
            FileInputStream in = new FileInputStream(file);
            long fileLen =file.length();
            byte[] fileContent = new byte[(int) fileLen];
            in.read(fileContent);
            content = new String(fileContent, StandardCharsets.UTF_8);
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content;
    }
    /**
     * Todo: Serialize the object to the local repository.
     * @throws Exception
     */
    public void writeObject() throws Exception{
        /**
         * Add your code here.
         */
        FileCreation.createDirectory(path, this.key.substring(0, 2));
        ObjectOutputStream file = new ObjectOutputStream(new FileOutputStream(path + File.separator + this.key.substring(0, 2) + File.separator + this.key.substring(2)));
        GitObject object = this;
        file.writeObject(object);
        file.close();
    }

    /**
     * Todo: Serialize the object and compress with zlib.
     * @throws Exception
     */
    public boolean compressWrite() throws Exception{
        /**
         * Add your code here.
         */
        GitObject object = this;
        String parentPath = path + File.separator + this.key.substring(0, 2);
        if(new File(path).exists()) {
            new File(parentPath).mkdirs();
            OutputStream os = new FileOutputStream(parentPath + File.separator + this.key.substring(2));
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ObjectOutputStream file = new ObjectOutputStream(out);
            file.writeObject(object);
            file.flush();
            byte[] bytes = out.toByteArray();
            ZLibUtils.compress(bytes, os);
            return true;
        }
        else{
            System.out.println("fatal: \"objects\" folder does not exist in the repository: .jit");
            return false;
        }
    }

    /**
     * Todo: Deserialize the object and decompress with zlib.
     * @throws Exception
     */
    public static byte[] deCompress(String id) throws Exception{
        /**
         * Add your code here.
         */
        if(id == null) return null;
        File object = new File(path + File.separator + id.substring(0, 2) + File.separator + id.substring(2));
        if(object.exists()) {
            InputStream is = new FileInputStream(path + File.separator + id.substring(0, 2) + File.separator + id.substring(2));
            return ZLibUtils.decompress(is);
        }
        else{
            System.out.printf("fatal: Not a valid object name %s\r\n", id);
            return null;
        }
    }

    public static GitObject deserialize(String Id) throws IOException {
        GitObject gitObject = null;
        try{
            /**
             * Todo: Add your code here.
             */
            byte[] bytes = deCompress(Id);
            if(bytes == null) return null;
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            ObjectInputStream file = new ObjectInputStream(in);
            gitObject = (GitObject) file.readObject();
            file.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        /* Todo: You should delete the return statement before you start. */
        return gitObject;
    }

}
